(function($, undefined) {
  /**
   * namespace
   * 
   * @constructor
   */
  $.cha = function() {
  };
  /**
   * create namespace if namesaces does not exist.
   * 
   * @param {String}
   *          namespace
   */
  $.cha.ns = function(namespace) {
    var spilit = namespace.split(".");
    var base = $.cha;
    for ( var i = 0; i < spilit.length; i++) {
      if (!base[spilit[i]]) {
        base[spilit[i]] = {};
      }
      base = base[spilit[i]];
    }
  };
  /**
   * cha.js's directory
   * 
   * @type {String}
   */
  $.cha.BASE_URL = (function() {
    var JS_FILE = "cha.js";
    var scripts = $('script');
    for ( var i = scripts.length - 1; i >= 0; --i) {
      var src = scripts[i].src;
      var qmark = src.lastIndexOf('?');
      var l = qmark == -1 ? src.length : qmark;
      if (src.substr(l - JS_FILE.length, JS_FILE.length) == JS_FILE) {
        return src.substr(0, l - JS_FILE.length);
      }
    }
    throw new Error(JS_FILE + " not found");
  }());

  /**
   * loaded script flag
   */
  $.cha.loadedScripts_ = {};

  $.cha.css = function(src) {
    if ($.cha.loadedScripts_[src+".css"]) {
      return;
    }
    var path = $.cha.replaceAll(src, ".", "/");
    var doc = window.document;
    doc.write('<link rel="stylesheet" href="' + $.cha.BASE_URL + path
        + '.css">');
    $.cha.loadedScripts_[src+".css"] = true;
  };
  
  /**
   * load script
   * 
   * @param {String}
   *          src
   */
  $.cha.js = function(src) {
    if ($.cha.loadedScripts_[src]) {
      return;
    }
    var path = $.cha.replaceAll(src, ".", "/");
    var doc = window.document;
    doc.write('<script type="text/javascript" src="' + $.cha.BASE_URL + path
        + '.js"></' + 'script>');
    $.cha.loadedScripts_[src] = true;
  };

  /**
   * loaded template
   */
  $.cha.loadedTemplate = {};

  /**
   * load template if first loading.
   * 
   * @param {String}
   *          src
   * @param {Function}
   *          callback;
   */
  $.cha.html = function(src, callback) {
    if ($.cha.loadedTemplate[src]) {
      if (callback) {
        callback();
      }
      return;
    }

    $.cha.loadText($.cha.replaceAll(src, ".", "/") + ".html", function(data) {
      $.template("cha." + src, data);
      $.cha.loadedTemplate[name] = true;
      if (callback) {
        callback();
      }
    });
  };

  /**
   * load text
   * 
   * @param {String}
   *          src
   * @param {Function}
   *          callback
   */
  $.cha.loadText = function(src, callback) {
    $.ajax({
      url : $.cha.BASE_URL + src,
      success : callback,
      dataType : "text",
      async : false
    });
  };

  /**
   * 
   * @param {String}
   *          input
   * @param {String}
   *          org
   * @param {String}
   *          dest
   * @returns
   */
  $.cha.replaceAll = function(input, org, dest) {
    return input.split(org).join(dest);
  };
  
  $.cha.namesort = function(a, b) {
    if (a.name() == b.name()) {
      return 0;
    }
    if (a.name() > b.name()) {
      return 1;
    }
    return -1;
  };

  $.cha.js("EventBus");

}(jQuery));